﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System.Text.RegularExpressions;

namespace downloadfilestool
{
    public partial class MainForm : Form
    {
        private List<SynFileInfo> m_DownloadList = new List<SynFileInfo>();

        private string lastAlbum = "";

       
        public MainForm()
        {
            InitializeComponent();
        }

        [DllImport("wininet.dll")]
        private static extern bool InternetGetConnectedState(out int connectionDescription, int reservedValue);

        private bool isConnected()
        {
            int num = 0;
            return MainForm.InternetGetConnectedState(out num, 0);
        }

        private void showinfo(string txt)
        {
            this.lblInfo.Text = txt;
            Application.DoEvents();
        }

        private void GetJsonInfo(SynFileInfo tf)
        {
            JToken jToken = JsonConvert.DeserializeObject<JToken>(this.HttpGet("http://www.ximalaya.com/tracks/" + tf.DocID + ".json"));
            tf.DownPath = jToken["play_path_64"].ToString();
            if (tf.DownPath.IndexOf("http://") < 0)
            {
                tf.DownPath = "http://fdfs.xmcdn.com/" + jToken["play_path_64"].ToString();
            }
            string value = jToken["duration"].ToString();
            tf.DocName = this.FixFileName(jToken["title"].ToString());
            tf.Album = this.FixFileName(jToken["album_title"].ToString());
            tf.duration = (int)Convert.ToDouble(value);
            this.mkdir(Application.StartupPath + "\\" + tf.Album + "\\");
            tf.SavePath = string.Concat(new string[]
            {
                Application.StartupPath,
                "\\",
                tf.Album,
                "\\",
                tf.DocName,
                ".mp3"
            });
        }

        private void StartNewWork()
        {
            try
            {
                SynFileInfo next = this.GetNext();
                if (next == null)
                {
                    MessageBox.Show("所有文件下载完毕!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                }
                else
                {
                    this.showinfo("分析:" + next.DocName);
                    this.GetJsonInfo(next);
                    next.RowObject.Cells["duration"].Value = (next.duration / 60).ToString() + "分钟";
                    this.showinfo("下载:" + next.DocName);
                    if (next.Album != this.lastAlbum)
                    {
                        this.lastAlbum = next.Album;
                        this.SaveAlbum(this.lastAlbum);
                    }
                    this.StartDownload(next);
                }
            }
            catch (Exception ex)
            {
                string text = "下载出现错误，请重试！若仍有问题，请联系作者！";
                LogHelper.WriteLog("StartNewWork" + text + ex.Message);
                this.showinfo(text);
            }
        }

        private void SaveAlbum(string album)
        {
            File.AppendAllText(Application.StartupPath + "\\下载列表.txt", string.Format("{0}\t{1}\r\n", album, DateTime.Now.ToString("yyyy-MM-dd")));
        }

        private void StartDownload(SynFileInfo sfi)
        {
            try
            {
                sfi.LastTime = DateTime.Now;
                WebClient expr_10 = new WebClient();
                expr_10.DownloadProgressChanged += new DownloadProgressChangedEventHandler(this.client_DownloadProgressChanged);
                expr_10.DownloadFileCompleted += new AsyncCompletedEventHandler(this.client_DownloadFileCompleted);
                expr_10.DownloadFileAsync(new Uri(sfi.DownPath), sfi.SavePath, sfi);
            }
            catch (Exception ex)
            {
                string text = "下载出现错误，请重试！若仍有问题，请联系作者！";
                LogHelper.WriteLog("StartDownload" + text + ex.Message);
                this.showinfo(text);
            }
        }

        private void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            try
            {
                SynFileInfo synFileInfo = (SynFileInfo)e.UserState;
                synFileInfo.SynProgress = e.ProgressPercentage + "%";
                double totalSeconds = (DateTime.Now - synFileInfo.LastTime).TotalSeconds;
                synFileInfo.SynSpeed = FileOperate.GetAutoSizeString(Convert.ToDouble((double)e.BytesReceived / totalSeconds), 2) + "/s";
                if (synFileInfo.RowObject.Cells["FileSize"].Value == null)
                {
                    synFileInfo.FileSize = e.TotalBytesToReceive;
                    synFileInfo.RowObject.Cells["FileSize"].Value = FileOperate.GetAutoSizeString((double)e.TotalBytesToReceive, 2);
                }
                synFileInfo.RowObject.Cells["SynProgress"].Value = synFileInfo.SynProgress;
                synFileInfo.RowObject.Cells["SynSpeed"].Value = synFileInfo.SynSpeed;
            }
            catch (Exception ex)
            {
                string text = "下载出现错误，请重试！若仍有问题，请联系作者！";
                LogHelper.WriteLog("client_DownloadProgressChanged" + text + ex.Message);
                this.showinfo(text);
            }
        }

        private void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
        {
            ((SynFileInfo)e.UserState).isComplete = true;
            this.StartNewWork();
        }

        private void mkdir(string dir)
        {
            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }
        }

        private string HttpGet(string url)
        {
            byte[] bytes = new WebClient().DownloadData(url);
            return Encoding.UTF8.GetString(bytes);
        }

        private SynFileInfo GetNext()
        {
            foreach (SynFileInfo current in this.m_DownloadList)
            {
                if (current.Selected && !current.isComplete)
                {
                    return current;
                }
            }
            return null;
        }

        private void btnAnalyze_Click(object sender, EventArgs e)
        {
            try
            {
                if (!this.isConnected())
                {
                    MessageBox.Show("未连接网络!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Hand);
                }
                else
                {
                    this.showinfo("正在获取...");
                    if (this.txtUrl.Text.Contains("/sound/"))
                    {
                        this.AnalyzeSigleDoc();
                    }
                    else
                    {
                        this.AnalyzeAlbum();
                    }
                }
            }
            catch (Exception ex)
            {
                string text = " 内容解析失败，请查看链接地址是否正确！若重试仍有问题，请联系作者！";
                LogHelper.WriteLog("btnAnalyze_Click" + text + ex.Message);
                this.showinfo(text);
            }
        }

        private void AnalyzeAlbum()
        {
            try
            {
                byte[] bytes = new WebClient().DownloadData(this.txtUrl.Text);
                string arg_2C_0 = Encoding.UTF8.GetString(bytes);
                this.showinfo("完成!");
                string value = Regex.Match(arg_2C_0, "<h1>([\\w\\W]*?)</h1>").Groups[1].Value;
                string pattern = "(?i)<li sound_id=\"(\\d*)\" class=\"\">[\\w\\W]*?hashlink[\\w\\W]*?>([\\w\\W]*?)</a>";
                foreach (Match match in Regex.Matches(arg_2C_0, pattern, RegexOptions.IgnoreCase | RegexOptions.Multiline))
                {
                    string[] values = new string[]
                    {
                        "true",
                        match.Groups[1].Value.Trim(),
                        value,
                        match.Groups[2].Value.Trim()
                    };
                    new DataGridViewRow();
                    int index = this.m_downlist.Rows.Add(values);
                    DataGridViewRow rowObject = this.m_downlist.Rows[index];
                    SynFileInfo item = new SynFileInfo
                    {
                        DocID = match.Groups[1].Value.Trim(),
                        DocName = match.Groups[2].Value.Trim(),
                        RowObject = rowObject,
                        Album = value,
                        Selected = true
                    };
                    this.m_DownloadList.Add(item);
                }
                this.showinfo("共" + this.m_DownloadList.Count.ToString());
            }
            catch (Exception ex)
            {
                string text = "内容解析失败，请查看链接地址是否正确！";
                LogHelper.WriteLog(text + ex.Message);
                this.showinfo(text);
            }
        }

        private void AnalyzeSigleDoc()
        {
            string expr_0B = this.txtUrl.Text;
            string docID = expr_0B.Substring(expr_0B.IndexOf("sound/") + 6);
            SynFileInfo synFileInfo = new SynFileInfo
            {
                Selected = true
            };
            synFileInfo.DocID = docID;
            this.GetJsonInfo(synFileInfo);
            string[] values = new string[]
            {
                "true",
                synFileInfo.DocID,
                synFileInfo.Album,
                synFileInfo.DocName
            };
            int index = this.m_downlist.Rows.Add(values);
            DataGridViewRow rowObject = this.m_downlist.Rows[index];
            synFileInfo.RowObject = rowObject;
            synFileInfo.RowObject.Cells["duration"].Value = (synFileInfo.duration / 60).ToString() + "分钟";
            this.m_DownloadList.Add(synFileInfo);
        }

        private string FixFileName(string s)
        {
            char[] arg_0D_0 = "\\/:*?\"<>|'".ToCharArray();
            char newChar = '_';
            char[] array = arg_0D_0;
            for (int i = 0; i < array.Length; i++)
            {
                char oldChar = array[i];
                s = s.Replace(oldChar, newChar);
            }
            return s;
        }

        private void btnDownload_Click(object sender, EventArgs e)
        {
            this.StartNewWork();
        }

        private void txtUrl_TextChanged(object sender, EventArgs e)
        {
            string text = Clipboard.GetText();
            if (text.StartsWith("http://www.ximalaya.com/"))
            {
                this.txtUrl.Text = text;
            }
        }

        private void btnOpenExplorer_Click(object sender, EventArgs e)
        {
            string startupPath = Application.StartupPath;
            Process.Start("Explorer.exe", startupPath);
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            this.m_downlist.Rows.Clear();
            this.m_DownloadList.Clear();
        }

        private void m_downlist_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex == 0 && e.RowIndex != -1)
            {
                this.m_downlist.Rows[e.RowIndex].Cells[0].Value = !Convert.ToBoolean(this.m_downlist.Rows[e.RowIndex].Cells[0].Value);
                this.m_DownloadList[e.RowIndex].Selected = false;
            }
        }

        private void lblLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            Process.Start("http://blog.csdn.net/suqingheangle/article/details/52995772");
        }

       
    }
}
